這次將延續 [DAY 2] 生成 (add_child) 來新增功能,所以要先準備好 Day2 的腳本。
先來回憶一下 Day2 我們做了什麼:在 Day2 我們做了一個點擊生成 scene 的功能,那我們這次除了點擊生成之外,還要讓生成的物件在指定時間後自主銷毀。
介紹計時器(Timer)
Counts down a specified interval and emits a signal on reaching 0. Can be set to repeat or "one-shot" mode.
從介紹中可以看到計時器會在一個指定時間區間歸零後發出信號(signal),可以設定成重複計時或是一次性計時。
因為我們要讓每個生成的物件各自計時因此我們在生成的方法中新增倒數計時的邏輯。
# 在 spawn 方法中建立一個 Timer 並命名為 timer
var timer = Timer.new()
接著介紹幾個 Timer 屬性
float wait_time [預設: 1.0]
set_wait_time(數值) setter
get_wait_time() getterThe wait time in seconds.
這是這次最主要的功能:計時時長,我們可以透過這個屬性設置期望的時長。
bool one_shot [預設: false]
set_one_shot(數值) setter
is_one_shot() getterIf true, the timer will stop when reaching 0. If false, it will restart.
當 on_shot 時,代表執行玩一次倒數後就會停止,否則會重新執行。
那接著根據上面的屬性設定我們的 Timer
設定前先暴露一個消除時間的參數方便未來修改
# 在最前面新增變數 destory_time
@export var destory_time:float = 1.0
接著設定屬性
# 設定時間
imer.set_wait_time(destory_time)
# 只要執行一次
imer.set_one_shot(true)
設定完成後接著我們建立一個方法來告訴 Timer 倒數完要做什麼
func _on_timer_timeout(objectToDestroy):
# 刪除傳入的物件
objectToDestroy.queue_free()
介紹新的方法 Signal 的 connect
int connect(callable: Callable, flags: int = 0)
Connects this signal to the specified callable.
這個方法可以讓我們的 Signal (Timer 中的 Signal 叫做 timeout,會在倒數結束後觸發)可以綁定要執行的方法,綁定的方式因為參數的型別是 Callable ,而我們的消滅方法也有參數需要輸入,所以需要透過 .bind() 來將參數綁到我們的 Callable
timer.timeout.connect(_on_timer_timeout.bind(godot))
最後再將我們的 Timer 加到我們的物件下並且開始計時
godot.add_child(timer)
timer.start()
完整檔案
extends Node
@export var to_be_created:PackedScene
@export var destory_time:float = 1.0
# Called when the node enters the scene tree for the first time.
func _ready():
pass
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
if Input.is_action_pressed("on_left_click"):
spawn()
func spawn():
var godot = to_be_created.instantiate()
godot.position = get_viewport().get_mouse_position()
add_child(godot)
var timer = Timer.new()
timer.set_wait_time(destory_time)
timer.set_one_shot(true)
timer.timeout.connect(_on_timer_timeout.bind(godot))
godot.add_child(timer)
timer.start()
func _on_timer_timeout(objectToDestroy):
objectToDestroy.queue_free()
:)